package com.alfayun.fiscalriskanalysis.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.alfayun.fiscalriskanalysis.security.customuserdetails.CustomUserDetailsService;
import com.alfayun.fiscalriskanalysis.user.Role;

@EnableWebSecurity
public class SecurityConfig {

	@Configuration
	@Order(1)
	public class ClientConfigurationAdapter extends WebSecurityConfigurerAdapter {
		
		@Override
	    public void configure(WebSecurity web) {
	        web.ignoring().antMatchers("/**/css/**", "/**/js/**", "/**/fonts/**", "/**/img/**",
	        		"/403", "/404", "/500");
	    }
		
		@Autowired
	    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
	        auth.userDetailsService(customUserDetailsService()).passwordEncoder(passwordEncoder())
	        	.and().inMemoryAuthentication().withUser("user").password("password").roles(Role.CLIENT.toString());
	    }
	 
	    @Override
		protected void configure(HttpSecurity http) throws Exception {
	        http
	        	.authorizeRequests()
	        		.antMatchers("/client/signUp", "/client/changePwd", "/client/checkUsername")
	        		.permitAll().anyRequest().authenticated()
	        		.and()
	        	.antMatcher("/client/**")
	            	.authorizeRequests().anyRequest().hasAnyRole(Role.CLIENT.toString())
	            	.and()
	            .formLogin()
	            	.loginPage("/client/login")
	            	.defaultSuccessUrl("/client/index")
	            	.permitAll()
	            	.and()
            	.logout()
					.logoutUrl("/client/logout")
					.logoutSuccessUrl("/client/login")
		            .permitAll()
		            .and()
	            .exceptionHandling()
	            .defaultAuthenticationEntryPointFor(
            		clientloginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/client/**"))
	            	.accessDeniedPage("/403");
	        http.csrf().disable();
	        http.headers().frameOptions().sameOrigin();
	    }
	}
	
	@Configuration
	@Order(2)
	public class AdminConfigurationAdapter extends WebSecurityConfigurerAdapter {
		
		@Override
	    public void configure(WebSecurity web) {
	        web.ignoring().antMatchers("/**/css/**", "/**/js/**", "/**/fonts/**", "/**/img/**",
	        		"/403", "/404", "/500");
	    }
		
		@Autowired
	    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
	        auth.userDetailsService(customUserDetailsService()).passwordEncoder(passwordEncoder())
	        	.and().inMemoryAuthentication().withUser("user").password("password").roles(Role.ADMIN.toString());
	    }
	 
	    @Override
		protected void configure(HttpSecurity http) throws Exception {
	        http
//		        .authorizeRequests()
//		    		.antMatchers("", "")
//		    		.permitAll().anyRequest().authenticated()
//		    		.and()
	        	.antMatcher("/admin/**")
	            	.authorizeRequests().anyRequest().hasRole(Role.ADMIN.toString())
	            	.and()
	            .formLogin()
	            	.loginPage("/admin/login")
	            	.defaultSuccessUrl("/admin/index")
	            	.permitAll()
	            	.and()
            	.logout()
					.logoutUrl("/admin/logout")
					.logoutSuccessUrl("/admin/login")
		            .permitAll()
		            .and()
		        .exceptionHandling()
	            .defaultAuthenticationEntryPointFor(
            		adminloginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/admin/**"))
	            	.accessDeniedPage("/403");
	        http.csrf().disable();
	        http.headers().frameOptions().sameOrigin();
	    }
	}
	
	@Configuration
	@Order(3)
	public class defaultConfigurationAdapter extends WebSecurityConfigurerAdapter {
		@Override
		public void configure(WebSecurity web) throws Exception {
			web.ignoring()
					.antMatchers("/**")
					.antMatchers("/static/**");
		}
	}
	
	@Bean
    public CustomUserDetailsService customUserDetailsService() {
    	return new CustomUserDetailsService();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
    	return new BCryptPasswordEncoder();
    }
    
    @Bean
    public AuthenticationEntryPoint clientloginUrlauthenticationEntryPoint(){
        return new LoginUrlAuthenticationEntryPoint("/client/login");
    }
    
    @Bean
    public AuthenticationEntryPoint adminloginUrlauthenticationEntryPoint(){
        return new LoginUrlAuthenticationEntryPoint("/admin/login");
    }

}
